#ifndef _3DSLOADER_H_
#define _3DSLOADER_H_

#include <fstream>
#include <iostream>
#include <list>
#include <vector>

#include "ModelStructs.h"
#include "Errors.h"

//------  these define the different color chunk types
#define RGBF   0x0010
#define RGB24  0x0011


enum ChunkIDenum {	
	 PRIMARY = 0x4D4D,

	 EDIT3DS       = 0x3D3D,
	 VERSION       = 0x0002,
	 MESHVERSION   = 0x3D3E,
	 EDITKEYFRAME  = 0xB000,

	 EDITMATERIAL  = 0xAFFF,
	 EDITOBJECT    = 0x4000,

	 MATNAME       = 0xA000, 
	 MATLUMINANCE  = 0xA010,
	 MATDIFFUSE    = 0xA020,
	 MATSPECULAR   = 0xA030,
	 MATSHININESS  = 0xA040,
	 MATMAP        = 0xA200,
	 MATMAPFILE    = 0xA300,

	 OBJTRIMESH    = 0x4100,

	 TRIVERT       = 0x4110,
	 TRIFACE       = 0x4120,
	 TRIFACEMAT    = 0x4130,
	 TRIUV         = 0x4140,
	 TRISMOOTH     = 0x4150,
	 TRILOCAL      = 0x4160,

	 KFMESH        = 0xB002,
	 KFHEIRARCHY   = 0xB030,
	 KFNAME        = 0xB010
};

//#pragma pack(push)
//#pragma pack(1)

struct Chunk
{
	unsigned short int m_ID;
	unsigned long m_length;	
	unsigned long m_readBytes;

	Chunk():m_ID(0), m_length(0), m_readBytes(0) {}
	void Reset() { m_ID=0; m_length=0; m_readBytes=0; }
};

//#pragma pack(pop)

//
// Klasa Loadera 3DS
class Load3DS
{
public:
	Load3DS();
	~Load3DS();
	int Load(const wchar_t *, std::list<Mesh*>*);

protected:
	std::list<Mesh*>* m_meshes;

	int ProcessNextObjectChunk(Chunk *a_chunk, Mesh* a_mesh);
	int ProcessNextChunk(Chunk *);
	int ComputeNormalInMesh(Mesh* a_mesh);
	bool ReadChunk(Chunk* );
	void MoveToEndOfChunkData(Chunk* );
	std::string ReadString(Chunk* );
	void FillVertexBuffer(Chunk* a_chunk, Mesh* a_mesh);
	void FillIndexBuffer(Chunk* a_chunk, Mesh* a_mesh);

private:	
	std::fstream m_file;
	
	Chunk * m_currentChunk;
	Chunk * m_tempChunk;

};


#endif
 